package com.yellow.orderservice.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yellow.orderservice.entity.Order;
import com.yellow.orderservice.exception.OrderAlreadyGrabbedException;
import com.yellow.orderservice.exception.UpdateFailedException;
import com.yellow.orderservice.mapper.OrderMapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.RandomStringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author: hy
 * @create: 2024-02-20
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Resource
    private OrderMapper orderMapper;

    @Resource
    private RedissonClient redissonClient;

    @Override
    public List<Order> selectOrderListByUserId(Integer userId) {

        return orderMapper.selectOrderListByUserId(userId);
    }

    @Override
    public List<Order> selectAllOrders() {

        return orderMapper.selectList(null);
    }

    @Override
    public String getCourierNameByOrderId(Integer orderId) {
        return orderMapper.getCourierNameByOrderId(orderId);
    }

    @Override
    @Retryable(retryFor = OptimisticLockingFailureException.class, maxAttempts = 3, backoff = @Backoff(delay = 100))
    @Transactional(rollbackFor = Exception.class)
    public void grabOrder(int orderId, String courierName) {
        // 检查订单是否可抢
        Order order = orderMapper.selectById(orderId);
        if (order == null || !"未派单".equals(order.getDeliveryStatus())) {
            throw new OrderAlreadyGrabbedException("The order has already been grabbed or does not exist.");
        }

        // 生成随机跟踪号
        String trackingNumber = generateTrackingNumber();

        // 更新订单状态
        order.setDeliveryStatus("正在拣货");
        order.setTrackingNumber(trackingNumber);
        order.setCourierName(courierName);

        // 执行更新操作
        int updatedRows = orderMapper.updateById(order);
        if (updatedRows == 0) {
            // 如果没有行被更新，可能是因为乐观锁导致的更新失败
            throw new UpdateFailedException("Failed to grab the order.");
        }
    }

    @Override
    public void insertOrder(Order order) {
         orderMapper.insert(order);
    }

    public Long countOrders(){
        return orderMapper.selectCount(null);
    }

    @Override
    public Order findByOrderId(Integer orderId) {

        return orderMapper.selectById(orderId);
    }

    @Override
    public void insertCustomerOrders(Integer customerId, Integer orderId,Long id) {
        orderMapper.insertCustomerOrders(customerId, orderId, id);
    }

    @Override
    public Integer countCustomerOrders() {
        return orderMapper.countCustomerOrders();
    }

    @Override
    public void incrementOrderViewCount(String orderId) {
        String lockKey = "order:view:lock:" + orderId;
        RLock lock = redissonClient.getLock(lockKey);

        try {
            // 获取锁
            lock.lock();

            // 获取当前查看次数
            String viewCountKey = "order:view:count:" + orderId;
            Integer currentCount = (Integer) redissonClient.getBucket(viewCountKey).get();
            currentCount = currentCount != null ? currentCount : 0;

            // 增加查看次数
            int newCount = currentCount + 1;

            // 将新的查看次数写回Redis
            redissonClient.getBucket(viewCountKey).set(newCount);

        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    @Override
    public int getOrderViewCount(String orderId) {
        String viewCountKey = "order:view:count:" + orderId;
        Integer currentCount = (Integer) redissonClient.getBucket(viewCountKey).get();
        return currentCount != null ? currentCount : 0;
    }

    private String generateTrackingNumber() {
        // 生成随机大写字母字符串
        String letters = RandomStringUtils.random(3, 65, 90, true, false);
        // 生成随机数字字符串
        String numbers = RandomStringUtils.randomNumeric(6);
        return letters + numbers;
    }


}
